#include <iostream>
#include <vector>

#include "inc/plateau.h"

Plateau::Plateau()
{
	
}

Plateau::~Plateau()
{
	pts.clear();
	data.clear();
	im.clear();
}

void Plateau::setCaseType(int _i, QString _t)
{
	data[_i]->setType( _t );
}

void Plateau::setCasePts(int _i, int _nb)
{
	data[_i]->setNbPions ( _nb );
}

Point* Plateau::getPoint(int _i)
{
	return pts[_i];
}

int Plateau::getNbPts()
{
	return (int)pts.size();
}

int Plateau::getCaseNbPions(int _i)
{
	return data[_i]->getNbPions();
}

void Plateau::addCase()
{
	data.push_back( new Case() );
}

void Plateau::addCase( Case* _c)
{
	Case* tmp = new Case ( _c );
	data.push_back( tmp );
}

void Plateau::addPoint( Point *_p )
{
	pts.push_back( _p );
}

void Plateau::deletePoint(Point *_p)
{
	for ( int i = 0 ; i < (int)data.size() ; i++ )
	{
		data[i]->deletePoint(_p);
	}
	
	for ( int i = 0 ; i < (int)pts.size() ; i++ )
	{
		if ( pts[i] == _p )
		{
			pts.erase( pts.begin()+i );
			return;
		}
	}
}

void Plateau::replacePoint(Point *_p1, Point *_p2)
{
	/* On remplace le point dans toutes les cases du plateau */ 
	for ( int i = 0 ; i < (int)data.size() ; i++ )
	{
		data[i]->replacePoint ( _p1, _p2 );
	}
	
	/* puis on regarde si une case n'a pas perdu assez de points pour etre supprimée (nbPts < 3) */
	for ( int i = 0 ; i < (int)data.size() ; i++ )
	{	
		if ( data[i]->getNbPts() < 3 )
		{
			/* On efface tous les points qu'il reste dans la case du plateau */
			for ( int j = 0 ; j < (int)data[i]->getNbPts() ; j++ )
				this->deletePoint( data[i]->getPoint(j) );
			/* On ecrase la case */
			data.erase( data.begin() + i );
		}
	}
	
	/* Puis on supprime _p1 du tableau de points du plateau */
	for ( int i = 0 ; i < (int)pts.size() ; i++ )
	{
		if ( _p1 == pts[i] )
		{
			pts.erase( pts.begin() + i );
			return;
		}
	}
}

Point* Plateau::newPoint(Point *_p)
{
	for ( int i = 0 ; i < (int)pts.size() ; i++ )
	{
		if ( abs( _p->getX() - pts[i]->getX() ) < 5 && abs( _p->getY() - pts[i]->getY() ) < 5 )
			return pts[i];
	}
	
	this->addPoint(_p);
	
	return _p;
}

Point* Plateau::pointClic(Point *_p)
{
	for ( int i = 0 ; i < (int)pts.size() ; i++ )
	{
		if ( abs( _p->getX() - pts[i]->getX() ) < 5 && abs( _p->getY() - pts[i]->getY() ) < 5 )
			return pts[i];
	}
	
	return NULL;
}

Point* Plateau::pointClic(Point *_p1, Point *_p2)
{
	for ( int i = 0 ; i < (int)pts.size() ; i++ )
	{
		if ( _p1 != _p2 && abs( _p1->getX() - pts[i]->getX() ) < 5 && abs( _p1->getY() - pts[i]->getY() ) < 5 )
			return pts[i];
	}
	
	return NULL;
}

void Plateau::initNeigbourhood()
{
	for ( int i = 0 ; i < (int)data.size() ; i++ )
	{
		data[i]->initNeighbourhood( data );
	}
}

bool Plateau::getBord(int _i)
{
	return data[_i]->getBord();
}

int Plateau::contains(Point *_p)
{
	for ( int i = 0 ; i < (int)data.size() ; i++ )
	{
		if ( data[i]->contains(_p) )
		{
			return i;
		}
	}
	
	return -1;
}

int Plateau::contains( int _x, int _y )
{
	for ( int i = 0 ; i < (int)data.size() ; i++ )
	{
		if ( data[i]->contains( _x, _y ) )
			return i;
	}
	
	return -1;
}

void Plateau::display()
{
	im.display();
}

void Plateau::displayCase(int _i, float _r, float _g, float _b, float _a)
{
	data[_i]->displayFilled(_r,_g,_b,_a);
}

void Plateau::displayCases()
{
	for ( int i = 0 ; i < (int)data.size() ; i++ )
		data[i]->display(1,0,0);
}

void Plateau::displayCaseType(int _i)
{
	data[_i]->displayType();
}

void Plateau::displayCaseNbPions(int _i)
{
	data[_i]->displayNbPions();
}

void Plateau::displayCasePions(int _i, Image _im)
{
	data[_i]->displayPions( _im );
}

void Plateau::displayNeighbourhood(int _i, float _r, float _g, float _b)
{
	data[_i]->displayNeighbourhood(_r,_g,_b);
}

void Plateau::displayPoints()
{
	glPointSize(5);
	glColor3f(1,0,0);
	glBegin(GL_POINTS);
	for ( int i = 0 ; i < (int)pts.size() ; i++ )
		glVertex2i ( pts[i]->getX(), pts[i]->getY() );
	glEnd();
}

void Plateau::displayAll()
{
	this->displayPoints();
	this->displayCases();
}

void Plateau::resize(int _oldW, int _oldH, int _w, int _h)
{
	for ( int i = 0 ; i < (int)pts.size() ; i++ )
	{
		float x = (float)pts[i]->getX()/(float)_oldW;
		float y = (float)pts[i]->getY()/(float)_oldH;
		pts[i]->setXY ( x * _w, y * _h );
	}
}
